package com.bdsy.system.shiro;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.ServletRequest;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.subject.WebSubject;
import org.springframework.beans.factory.annotation.Autowired;

import com.bdsy.common.utils.HttpContextUtils;
import com.bdsy.common.utils.IPUtils;
import com.bdsy.common.utils.UUIDUtil;
import com.bdsy.system.model.Authorization;
import com.bdsy.system.model.Permission;
import com.bdsy.system.model.User;
import com.bdsy.system.model.UserLog;
import com.bdsy.system.service.AuthorizationService;
import com.bdsy.system.service.PermissionService;
import com.bdsy.system.service.UserLogService;
import com.bdsy.system.service.UserService;

public class UserRealm extends AuthorizingRealm {
	
    @Autowired
    private UserService userService;
    
    @Autowired
    private AuthorizationService authorizationService;
    
    @Autowired
	private UserLogService userLogService;
    
    @Autowired
    private PermissionService permissionService;
    
    /**
     * 授权(验证权限时调用)
     */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		User user = (User)principals.getPrimaryPrincipal();
		
		String userName = user.getLoginName();
		String userId = user.getUserId();
		
		List<String> permsList = null;
		
		//系统管理员，拥有最高权限
		 if("admin".equals(userName)){
			List<Authorization> authList = authorizationService.getAuthList();
			permsList = new ArrayList<>(authList.size());
			for(Authorization auth : authList){
				permsList.add(auth.getAuthUrl());
			}
		}else{
			permsList = userService.queryAllPerms(userId);
		}

		//用户权限列表
		Set<String> permsSet = new HashSet<String>();
		for(String perms : permsList){
			if(StringUtils.isBlank(perms)){
				continue;
			}
			permsSet.addAll(Arrays.asList(perms.trim().split(",")));
		}
		
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
		info.setStringPermissions(permsSet);
		return info;
	}

	/**
	 * 认证(登录时调用)
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		UsernamePasswordToken upToken = (UsernamePasswordToken) token;
		//在loginController做过非空判断
		String loginame = (String)token.getPrincipal();
		String password = new String((char[]) token.getCredentials());
        //查询用户信息
		ServletRequest servletRequest = null;
		HttpServletRequest request=(HttpServletRequest)servletRequest;
		UserLog userLog = new UserLog();
        User user = userService.getUsername(loginame);
        
        //账号不存在
        if(user == null) {
        	request = HttpContextUtils.getHttpServletRequest();
	    	userLog.setUserLogId(UUIDUtil.randomUUID());
	    	userLog.setUserName("未知");
	    	userLog.setLoginName(loginame);
	    	userLog.setIp(IPUtils.getIpAddr(request));
	    	userLog.setStatus(0);
	    	userLog.setLoginTime(new Date());
	    	this.userLogService.addUserLog(userLog);
            throw new UnknownAccountException("账号或密码不正确");
        }
        
        //密码错误
        if(!password.equals(user.getLoginPassword())) {
        	request = HttpContextUtils.getHttpServletRequest();
	    	userLog.setUserLogId(UUIDUtil.randomUUID());
	    	userLog.setUserName("未知");
	    	userLog.setLoginName(loginame);
	    	userLog.setIp(IPUtils.getIpAddr(request));
	    	userLog.setStatus(0);
	    	userLog.setLoginTime(new Date());
	    	this.userLogService.addUserLog(userLog);
            throw new IncorrectCredentialsException("账号或密码不正确");
        }
        
        //账号锁定
        if(user.getUserStatus() == 2){
        	request = HttpContextUtils.getHttpServletRequest();
	    	userLog.setUserLogId(UUIDUtil.randomUUID());
	    	userLog.setUserName("未知");
	    	userLog.setLoginName(loginame);
	    	userLog.setIp(IPUtils.getIpAddr(request));
	    	userLog.setStatus(0);
	    	userLog.setLoginTime(new Date());
	    	this.userLogService.addUserLog(userLog);
        	throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        
        if(user != null){
        	if(password.equals(user.getLoginPassword())){
        		if(user.getUserStatus() == 1 ){
        			request = HttpContextUtils.getHttpServletRequest();
        	    	userLog.setUserLogId(UUIDUtil.randomUUID());
        	    	userLog.setUserName(user.getUserName());
        	    	userLog.setLoginName(user.getLoginName());
        	    	userLog.setIp(IPUtils.getIpAddr(request));
        	    	userLog.setStatus(1);
        	    	userLog.setLoginTime(new Date());
        	    	this.userLogService.addUserLog(userLog);
        	    	userService.updateUserDate(new Date(), UUIDUtil.randomUUID(),user.getUserId());
        	    	String apid = "0";
        			List<Permission> listPermission = permissionService.getAuthByid(user.getUserId(), apid);
        			ShiroUtils.setSessionAttribute("user", user);
        			ShiroUtils.setSessionAttribute("listPermission", listPermission);
        		}
        	}
        }
        
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName());
        return info;
	}

}
